package com.gitee.wsl.common.chart.sample.rose

import android.graphics.*
import com.gitee.wsl.android.ext.math.calcArcEndPointXY
import com.gitee.wsl.common.chart.sample.pie.model.PieData
import com.gitee.wsl.common.chart.sample.pie.PieChart
import com.gitee.wsl.android.ui.ext.type.drawRotateText
import com.gitee.wsl.android.ui.ext.type.textHeight
import com.gitee.wsl.math.Math
import com.gitee.wsl.jvm.math.add
import com.gitee.wsl.jvm.math.div
import com.gitee.wsl.jvm.math.mul
import com.gitee.wsl.jvm.math.sub
import timber.log.Timber

/**
 * @ClassName RoseChart
 * @Description  南丁格尔图基类
 * @author XiongChuanLiang<br/>(xcl_168@aliyun.com)
 *
 */
class RoseChart :PieChart() {
    /**
     * 内部背景画笔
     */
     val innerPaint: Paint by lazy {
        Paint().apply {
            color = Color.rgb(68, 68, 68)
            style = Paint.Style.FILL
            isAntiAlias = true
        }
    }
     var isShowInner = true
    
    /**
     * 设置各扇区间隔角度
     */
     var intervalAngle = 0f

    /**
     * 用于绘制背景线，圈的画笔
     */
     val bgPaint: Paint by lazy {
       Paint(Paint.ANTI_ALIAS_FLAG).apply {
           style = Paint.Style.STROKE
           isAntiAlias = true
       }
    }
    /**
     * 背景直线
     */
     var isShowBgLines = false
     var isShowBgCircle = false
     var bgSegList = mutableMapOf<Float, Int>()
     var showBgLineColor = Color.BLACK
    
    /**
     * 标签显示在外环上
     */
     var isShowOuterLabels = false

   /**
    * 指定要显示的线个数
    **/
    var bgLineCount = 0f
    
    init {
        labelPaint.color = Color.WHITE
        labelPaint.textSize = 22f
        labelPaint.textAlign = Paint.Align.CENTER
    }

    /**
     * 绘制背景直线与圈
     * @param canvas 画布
     */
    private fun drawBGCircle(canvas: Canvas) {
        if (!isShowBgCircle) return
        val radius: Float = radius
        
        bgSegList.forEach { (key, value) ->
            val newRadius = Math.mul(radius, key)
            if (newRadius.compareTo(0.0f) == 1) {
                bgPaint.color = value
                canvas.drawCircle(
                    bodyViewport.centerX, bodyViewport.centerY,
                    newRadius, bgPaint
                )
            }
        }
    }

    private fun drawBGLines(canvas: Canvas) {
        if (!isShowBgLines) return
        if (0f == bgLineCount) return
        val totalAngle = (360 - intervalAngle * bgLineCount).toInt()
        val currAngle = totalAngle / bgLineCount
        val radius: Float = radius
        var offsetAngle = offsetAngle
        for (i in 0 until bgLineCount.toInt()) {
            val pointbg = Math.calcArcEndPointXY(
                bodyViewport.centerX, bodyViewport.centerY,
                radius, offsetAngle + intervalAngle + currAngle / 2
            )
            bgPaint.color = showBgLineColor
            canvas.drawLine(
                bodyViewport.centerX, bodyViewport.centerY,
                pointbg.x, pointbg.y, bgPaint
            )
            offsetAngle = Math.add(Math.add(offsetAngle, currAngle), intervalAngle)
        }
    }

    private fun getLabelRadius(): Float {
        var labelRadius = 0f
        val radius: Float = radius
        labelRadius = if (isShowOuterLabels) {
            radius + labelPaint.textHeight
        } else {
            radius - radius / 2 / 2
        }
        return labelRadius
    }


    /**
     * 绘制图
     */
    override fun drawPlot(canvas: Canvas): Boolean {
        //计算中心点坐标
        val cirX: Float = bodyViewport.centerX
        val cirY: Float = bodyViewport.centerY
        val radius: Float = radius
        var arcAngle = 0.0f
        var newRaidus = 0.0f

        //数据源
        val chartDataSource: List<PieData> = dataSet
        if (chartDataSource.isEmpty()) {
            Timber.d( "数据源为空.")
            return false
        }

        //内环
        if (isShowInner) canvas.drawCircle(cirX, cirY, radius, innerPaint)

        //画背景
        drawBGCircle(canvas)
        //画背景直线
        drawBGLines(canvas)

        //依参数个数，算出总个要算多少个扇区的角度	 		
        val totalAngle = (360 - intervalAngle * chartDataSource.size).toInt()
        arcAngle = (totalAngle / chartDataSource.size).toFloat()

        //percentage = 360 / chartDataSource.size();
        //percentage = (float)(Math.round(percentage *100))/100; 		
        arcAngle = Math.div(Math.mul(arcAngle, 100f), 100f)
        if (!validateAngle(arcAngle)) {
            Timber.d( "计算出来的扇区角度小于等于0度,不能绘制.")
            return false
        }
        val labelRadius = getLabelRadius()
        for (cData in chartDataSource) {
            arcPaint.color = cData.sliceColor

            //将百分比转换为新扇区的半径    
            val p = cData.percentage / 100
            newRaidus = Math.mul(radius, p.toFloat())
            newRaidus = Math.div(Math.mul(newRaidus, 100f), 100f)

            //newRaidus = (float) (radius * (cData.getPercentage()/ 100));  
            //newRaidus = (float)(Math.round(newRaidus *100))/100;    

            //在饼图中显示所占比例   
            val nRF = RectF(
                Math.sub(cirX, newRaidus), Math.sub(cirY, newRaidus),
                Math.add(cirX, newRaidus), Math.add(cirY, newRaidus)
            )
            canvas.drawArc(nRF, offsetAngle + intervalAngle, arcAngle, true, arcPaint)

            //标识  
            val label = cData.label
            if ("" !== label) {
                //计算百分比标签 
                val point = Math.calcArcEndPointXY(
                    cirX, cirY, labelRadius, offsetAngle + intervalAngle + arcAngle / 2
                )

                //请自行在回调函数中处理显示格式
                canvas.drawRotateText(
                    label,
                    point.x, point.y, cData.itemLabelRotateAngle,
                     labelPaint
                )
            }

            //下次的起始角度  
            offsetAngle = Math.add(Math.add(offsetAngle, arcAngle), intervalAngle)
        }
        return true
    }

}